<template>
  <AxiomLayout :columns="[{id: 'config', width: '520px'}, {id: 'preview', width: '1fr'}]" class="h-100">
    <!-- Left Panel: Configurations -->
    <template #col-config>
        <AxiomCard class="h-100 d-flex flex-column">
            <template #header>
                <AxiomText weight="bold">配置</AxiomText>
            </template>
            <div class="flex-1 overflow-y-auto pt-3">
                <AxiomGroup direction="vertical" gap="large">
                    <AxiomCard>
                        <template #header><AxiomText weight="bold" size="medium">预设策略</AxiomText></template>
                        <AxiomForm label-position="top">
                            <AxiomFormItem label="选择预设索引策略">
                                <AxiomSelect
                                    :model-value="config.strategy_name"
                                    @update:model-value="$emit('strategy-changed', $event)"
                                    :options="strategyOptions"
                                    placeholder="选择一个预设策略将覆盖当前流水线"
                                    block
                                />
                            </AxiomFormItem>
                        </AxiomForm>
                    </AxiomCard>

                    <AxiomCard v-if="recommendedStrategy">
                        <template #header><AxiomText weight="bold" size="medium">智能推荐</AxiomText></template>
                        <AxiomGroup direction="vertical" gap="normal">
                             <AxiomText type="success">推荐策略: {{ recommendedStrategyLabel }}</AxiomText>
                             <AxiomBlockquote v-if="recommendationReason" class="mt-2" type="info" style="white-space: pre-wrap;">
                                 {{ recommendationReason }}
                             </AxiomBlockquote>
                        </AxiomGroup>
                    </AxiomCard>
                    
                    <AxiomCard>
                        <template #header>
                            <AxiomGroup justify="space-between" align="center">
                                <AxiomText weight="bold" size="medium">处理流水线</AxiomText>
                                <AxiomButton type="primary" icon="plus" @click="addPipeline" text circle/>
                            </AxiomGroup>
                        </template>
                        <AxiomGroup direction="vertical" gap="normal">
                            <AxiomCard v-for="(pipeline, index) in config.pipelines" :key="index" bordered>
                                <template #header>
                                    <AxiomGroup justify="space-between" align="center">
                                        <AxiomText weight="bold" size="small">流水线 {{ index + 1 }}</AxiomText>
                                        <AxiomButton icon="delete" @click="removePipeline(index)" text circle type="danger"/>
                                    </AxiomGroup>
                                </template>
                                <AxiomForm label-position="top">
                                    <AxiomFormItem label="集合名称后缀">
                                        <AxiomInput
                                        :model-value="pipeline.collection_name_suffix"
                                        @update:model-value="updatePipelineConfig(index, 'collection_name_suffix', $event)"
                                        placeholder="例如: _raw, _summary"
                                        />
                                    </AxiomFormItem>
                                    <AxiomFormItem label="分块模式">
                                        <AxiomSelect
                                        :model-value="pipeline.parser_type"
                                        @update:model-value="updatePipelineConfig(index, 'parser_type', $event)"
                                        :options="parserTypeOptions"
                                        block
                                        />
                                    </AxiomFormItem>

                                    <!-- Dynamic forms based on parser_type -->
                                    <div v-if="pipeline.parser_type === 'sentence_splitter' && pipeline.sentence_splitter_config">
                                        <AxiomFormItem label="分块大小"><AxiomInputNumber :model-value="pipeline.sentence_splitter_config.chunk_size" @update:model-value="updatePipelineSubConfig(index, 'sentence_splitter_config', 'chunk_size', $event)" :min="100"/></AxiomFormItem>
                                        <AxiomFormItem label="重叠大小"><AxiomInputNumber :model-value="pipeline.sentence_splitter_config.chunk_overlap" @update:model-value="updatePipelineSubConfig(index, 'sentence_splitter_config', 'chunk_overlap', $event)" :min="0"/></AxiomFormItem>
                                        <AxiomFormItem label="段落分隔符"><AxiomInput :model-value="pipeline.sentence_splitter_config.paragraph_separator" @update:model-value="updatePipelineSubConfig(index, 'sentence_splitter_config', 'paragraph_separator', $event)"/></AxiomFormItem>
                                        <AxiomFormItem label="二级分块正则"><AxiomInput :model-value="pipeline.sentence_splitter_config.secondary_chunking_regex" @update:model-value="updatePipelineSubConfig(index, 'sentence_splitter_config', 'secondary_chunking_regex', $event)"/></AxiomFormItem>
                                        <AxiomFormItem label="包含上下文关联"><AxiomSwitch :model-value="pipeline.sentence_splitter_config.include_prev_next_rel" @update:model-value="updatePipelineSubConfig(index, 'sentence_splitter_config', 'include_prev_next_rel', $event)"/></AxiomFormItem>
                                    </div>

                                    <div v-if="pipeline.parser_type === 'token_splitter' && pipeline.token_splitter_config">
                                        <AxiomFormItem label="分块大小"><AxiomInputNumber :model-value="pipeline.token_splitter_config.chunk_size" @update:model-value="updatePipelineSubConfig(index, 'token_splitter_config', 'chunk_size', $event)" :min="100"/></AxiomFormItem>
                                        <AxiomFormItem label="重叠大小"><AxiomInputNumber :model-value="pipeline.token_splitter_config.chunk_overlap" @update:model-value="updatePipelineSubConfig(index, 'token_splitter_config', 'chunk_overlap', $event)" :min="0"/></AxiomFormItem>
                                        <AxiomFormItem label="分隔符"><AxiomInput :model-value="pipeline.token_splitter_config.separator" @update:model-value="updatePipelineSubConfig(index, 'token_splitter_config', 'separator', $event)"/></AxiomFormItem>
                                        <AxiomFormItem label="包含上下文关联"><AxiomSwitch :model-value="pipeline.token_splitter_config.include_prev_next_rel" @update:model-value="updatePipelineSubConfig(index, 'token_splitter_config', 'include_prev_next_rel', $event)"/></AxiomFormItem>
                                    </div>
                                    
                                    <div v-if="pipeline.parser_type === 'semantic_splitter' && pipeline.semantic_splitter_config">
                                        <AxiomFormItem label="缓冲区大小"><AxiomInputNumber :model-value="pipeline.semantic_splitter_config.buffer_size" @update:model-value="updatePipelineSubConfig(index, 'semantic_splitter_config', 'buffer_size', $event)" :min="1"/></AxiomFormItem>
                                        <AxiomFormItem label="断点阈值"><AxiomInputNumber :model-value="pipeline.semantic_splitter_config.breakpoint_percentile_threshold" @update:model-value="updatePipelineSubConfig(index, 'semantic_splitter_config', 'breakpoint_percentile_threshold', $event)" :min="80" :max="99"/></AxiomFormItem>
                                        <AxiomFormItem label="嵌入模型"><AxiomSelect :model-value="pipeline.semantic_splitter_config.embedding_profile_name" @update:model-value="updatePipelineSubConfig(index, 'semantic_splitter_config', 'embedding_profile_name', $event)" :options="embeddingProfileOptions" :loading="embeddingProfilesLoading" block/></AxiomFormItem>
                                        <AxiomFormItem label="包含上下文关联"><AxiomSwitch :model-value="pipeline.semantic_splitter_config.include_prev_next_rel" @update:model-value="updatePipelineSubConfig(index, 'semantic_splitter_config', 'include_prev_next_rel', $event)"/></AxiomFormItem>
                                    </div>
                                    
                                    <div v-if="pipeline.parser_type === 'markdown_node' && pipeline.markdown_node_parser_config">
                                        <AxiomFormItem label="包含上下文关联"><AxiomSwitch :model-value="pipeline.markdown_node_parser_config.include_prev_next_rel" @update:model-value="updatePipelineSubConfig(index, 'markdown_node_parser_config', 'include_prev_next_rel', $event)"/></AxiomFormItem>
                                    </div>
                                </AxiomForm>
                            </AxiomCard>
                            <AxiomEmpty v-if="!config.pipelines || config.pipelines.length === 0" description="暂无流水线，请点击加号添加。" />
                        </AxiomGroup>
                    </AxiomCard>
                </AxiomGroup>
            </div>
        </AxiomCard>
    </template>
    
    <!-- Right Panel: Chunking Preview -->
    <template #col-preview>
        <AxiomCard class="h-100 d-flex flex-column">
             <template #header>
                <AxiomGroup justify="space-between" align="center">
                    <AxiomSelect
                        :model-value="selectedDocument ? selectedDocument.document_id : null"
                        @update:model-value="$emit('update:selected-document', documents.find(d => d.document_id === $event))"
                        :options="documentPreviewOptions"
                        placeholder="选择文档进行预览"
                        style="width: 250px; margin-right: 16px;"
                        block
                    />
                    <AxiomSelect
                        v-model="selectedPreviewPipelineIndex"
                        :options="pipelinePreviewOptions"
                        placeholder="选择流水线进行预览"
                        style="width: 250px;"
                        block
                    />
                    <AxiomButton type="primary" @click="$emit('refresh-preview')" :loading="chunkingLoading">刷新预览</AxiomButton>
                </AxiomGroup>
            </template>
            
            <div class="flex-1 overflow-y-auto pt-3">
                 <AxiomLoading v-if="chunkingLoading" text="正在生成分块预览..." class="h-100" />
                <div v-else-if="activePreviewData">
                    <AxiomGroup direction="vertical" gap="medium">
                        <AxiomCard v-for="(node, nIndex) in activePreviewData.split_nodes" :key="node.id || nIndex" bordered>
                            <template #header>
                                <AxiomGroup justify="space-between" align="center">
                                    <AxiomText weight="bold" size="small">分块 #{{ nIndex + 1 }}</AxiomText>
                                    <AxiomText type="secondary" size="small">ID: {{ node.id }}</AxiomText>
                                </AxiomGroup>
                            </template>
                            <AxiomCode :code="node.text" language="text" :show-line-numbers="false" class="mb-3" />
                            <AxiomGroup direction="vertical" gap="small" class="text-sm">
                                <AxiomGroup justify="space-between" align="start" gap="small">
                                    <AxiomText weight="bold" size="small" class="mr-2 flex-shrink-0">元数据:</AxiomText>
                                    <AxiomCode :code="JSON.stringify(node.metadata, null, 2)" language="json" style="width: 100%;" />
                                </AxiomGroup>
                                <AxiomGroup justify="space-between" gap="small">
                                    <AxiomText weight="bold" size="small">前置节点ID:</AxiomText>
                                    <AxiomText size="small">{{ node.prev_node_id || '无' }}</AxiomText>
                                </AxiomGroup>
                                <AxiomGroup justify="space-between" gap="small">
                                    <AxiomText weight="bold" size="small">后置节点ID:</AxiomText>
                                    <AxiomText size="small">{{ node.next_node_id || '无' }}</AxiomText>
                                </AxiomGroup>
                            </AxiomGroup>
                        </AxiomCard>
                    </AxiomGroup>
                     <AxiomEmpty v-if="!activePreviewData.split_nodes || activePreviewData.split_nodes.length === 0" description="此流水线没有生成分块。" />
                </div>
                 <AxiomEmpty v-else description="请从左侧选择一个文档并点击“刷新预览”按钮。" class="h-100" />
            </div>
        </AxiomCard>
    </template>
  </AxiomLayout>
</template>

<script setup>
import { ref, watch, computed } from 'vue';
import {
    AxiomLayout, AxiomGroup, AxiomSelect, AxiomFormItem,
    AxiomButton, AxiomEmpty, AxiomTitle, AxiomBlockquote,
    AxiomLoading, AxiomCard, AxiomText, AxiomSwitch, AxiomInput, AxiomCode,
    AxiomToolbar, AxiomInputNumber
} from 'axiom-view';

const props = defineProps({
  documents: { type: Array, required: true },
  selectedDocument: { type: Object, default: null },
  config: { type: Object, required: true },
  strategyOptions: { type: Array, required: true },
  recommendedStrategy: { type: String, default: '' },
  recommendationReason: { type: String, default: '' },
  parserTypeOptions: { type: Array, required: true },
  embeddingProfileOptions: { type: Array, required: true },
  embeddingProfilesLoading: { type: Boolean, default: false },
  chunkedPreview: { type: Array, required: true },
  chunkingLoading: { type: Boolean, default: false },
});

const emit = defineEmits(['update:config', 'update:selected-document', 'strategy-changed', 'refresh-preview']);

const recommendedStrategyLabel = computed(() => {
    if (!props.recommendedStrategy || !props.strategyOptions) {
        return '';
    }
    const foundOption = props.strategyOptions.find(opt => opt.value === props.recommendedStrategy);
    return foundOption ? foundOption.label : props.recommendedStrategy;
});

const documentPreviewOptions = computed(() => {
    return props.documents.map(doc => ({
        value: doc.document_id,
        label: doc.original_file_name || `文档ID: ${doc.document_id}`
    }));
});


// --- Preview State ---
const selectedPreviewPipelineIndex = ref('0');

const pipelinePreviewOptions = computed(() => {
    return props.config.pipelines.map((p, index) => ({
        value: `${index}`,
        label: p.collection_name_suffix ? `流水线 ${index + 1} (${p.collection_name_suffix})` : `流水线 ${index + 1}`,
    }));
});

const activePreviewData = computed(() => {
    if (!props.chunkedPreview || props.chunkedPreview.length === 0) return null;
    const index = parseInt(selectedPreviewPipelineIndex.value, 10);
    // The preview data might not align perfectly with pipelines if a refresh hasn't happened.
    // So we just find the first available preview.
    return props.chunkedPreview[index] || props.chunkedPreview[0];
});

// --- Pipeline Management ---

const getDefaultConfigForParser = (parserType) => {
    switch(parserType) {
        case 'sentence_splitter':
            return { chunk_size: 1024, chunk_overlap: 200, paragraph_separator: "\\n\\n", secondary_chunking_regex: "[^,.;。？！]+[,.;。？！]?", include_prev_next_rel: true };
        case 'token_splitter':
            return { chunk_size: 1024, chunk_overlap: 200, separator: "\\n\\n", include_prev_next_rel: true };
        case 'semantic_splitter':
            return { buffer_size: 1, breakpoint_percentile_threshold: 95, embedding_profile_name: props.embeddingProfileOptions.length > 0 ? props.embeddingProfileOptions[0].value : null, include_prev_next_rel: true };
        case 'markdown_node':
            return { include_prev_next_rel: true };
        default: return {};
    }
};

function addPipeline() {
  const newPipeline = {
    parser_type: 'sentence_splitter',
    collection_name_suffix: `_pipeline_${props.config.pipelines.length + 1}`,
    sentence_splitter_config: getDefaultConfigForParser('sentence_splitter'),
    token_splitter_config: null,
    semantic_splitter_config: null,
    markdown_node_parser_config: null,
  };
  const newPipelines = [...props.config.pipelines, newPipeline];
  emit('update:config', { ...props.config, pipelines: newPipelines });
}

function removePipeline(indexToRemove) {
  const newPipelines = props.config.pipelines.filter((_, index) => index !== indexToRemove);
  emit('update:config', { ...props.config, pipelines: newPipelines });
}

function updatePipelineConfig(index, key, value) {
  const newPipelines = [...props.config.pipelines];
  const pipelineToUpdate = { ...newPipelines[index] };
  pipelineToUpdate[key] = value;

  if (key === 'parser_type') {
    pipelineToUpdate.sentence_splitter_config = null;
    pipelineToUpdate.token_splitter_config = null;
    pipelineToUpdate.semantic_splitter_config = null;
    pipelineToUpdate.markdown_node_parser_config = null;
    
    const configKey = `${value}_config`;
    // 后端对markdown的配置对象是markdown_node_parser_config
    if (value === 'markdown_node') {
        pipelineToUpdate['markdown_node_parser_config'] = getDefaultConfigForParser(value);
    } else {
        pipelineToUpdate[configKey] = getDefaultConfigForParser(value);
    }
  }

  newPipelines[index] = pipelineToUpdate;
  emit('update:config', { ...props.config, pipelines: newPipelines });
}

function updatePipelineSubConfig(pipelineIndex, configKey, subKey, value) {
  const newPipelines = [...props.config.pipelines];
  const pipelineToUpdate = { ...newPipelines[pipelineIndex] };

  if (!pipelineToUpdate[configKey]) {
    pipelineToUpdate[configKey] = {};
  }

  pipelineToUpdate[configKey] = { ...pipelineToUpdate[configKey], [subKey]: value };
  newPipelines[pipelineIndex] = pipelineToUpdate;
  emit('update:config', { ...props.config, pipelines: newPipelines });
}


watch(() => props.config.pipelines, (newVal, oldVal) => {
    if (newVal.length !== oldVal.length) {
        const newIndex = `${newVal.length - 1}`;
        if (newVal.length > 0 && selectedPreviewPipelineIndex.value !== newIndex) {
             selectedPreviewPipelineIndex.value = newIndex;
        }
    }
}, { deep: true });
</script> 